/*
 * File:   RFID.c
 * Author: Ian Stansell
 *
 * Created on April 7, 2014, 1:38 PM
 */

/* Potion Combinations:
 *
 * Potion 1 (HEAL): any combo of ingredient 1, 2, and 3
 * Potion 2 (ENVENOM): any combo of ingredient 1, 3, and 4
 * Potion 3 (POWER-UP): any combo of ingredient 1, 2, and 4
 * Potion 4 (EXPLOSION): any combo of ingredient 2, 3, and 4
 * Any other combination is invalid and will not cause a reaction
 *
 *  To Add or Remove potions, change the bottom of the "ReadIngred" function
 */

#include <stdio.h>
#include <stdlib.h>
#include <usart.h>
#include <delays.h>
#include "RGB_TLC5947.h"
#include <p18f26k80.h>

// sm 130 valid blocks
const char blockOne[16] = {0x00, 0x00, 0x00, 0x00,
                            0x00, 0x00, 0x00, 0x00,
                            0x00, 0x00, 0x00, 0x00,
                            0x00, 0x00, 0x00, 0x00}; // default
const char blockTwo[16] = {0x40, 0x40, 0x40, 0x40,
                            0x40, 0x40, 0x40, 0x40,
                            0x40, 0x40, 0x40, 0x40,
                            0x40, 0x40, 0x40, 0x40}; // potion 1
const char blockThree[16] = {0x80, 0x80, 0x80, 0x80,
                            0x80, 0x80, 0x80, 0x80,
                            0x80, 0x80, 0x80, 0x80,
                            0x80, 0x80, 0x80, 0x80}; // potion 2
const char blockFour[16] = {0xC0, 0xC0, 0xC0, 0xC0,
                            0xC0, 0xC0, 0xC0, 0xC0,
                            0xC0, 0xC0, 0xC0, 0xC0,
                            0xC0, 0xC0, 0xC0, 0xC0}; // potion 3

// tag arrays
const char tagOne[12] = {'7', '2', '0', '0', '4', '1', '0' , '0', '7', '7', '4', '4'};
const char tagTwo[12] = {'7', '2', '0', '0', '4', '1', '0', 'E', 'B', '2', '8', 'F'};
const char tagThree[12] = {'7', '2', '0', '0', '4', '0', 'D', '0' , '0', '0', 'E', '2'};
const char tagFour[12] = {'7', '2', '0', '0', '4', '0', 'A', 'F', '7', 'C', 'E', '1'};


void initRFID(void);
void selectTag(void);
void authenticate(void);
int readBlock(void);
void writeBlock(int potNumb);
int readIngred(void);
void writePotion(int potNum);
int readPotion(void);
void antennaOff(void);
void antennaOn(void);

int y;
int z;
int x;

void initRFID(void){

    //Setup second UART for ID-12LA
    Open2USART(USART_TX_INT_OFF & USART_RX_INT_OFF
            & USART_ASYNCH_MODE & USART_EIGHT_BIT
            & USART_CONT_RX & USART_BRGH_HIGH, 103);

    // Setup first UART for sm130
    Open1USART(USART_TX_INT_OFF & USART_RX_INT_OFF
            & USART_ASYNCH_MODE & USART_EIGHT_BIT
            & USART_CONT_RX & USART_BRGH_HIGH, 51);
  
    antennaOff();

}


void selectTag(void){
    // select the tag in field to read/write from/to

    unsigned char response[10] = { {0x00} };
    unsigned char command[5] = {0xFF, 0x00, 0x01, 0x83, 0x84};


    while(response[2] != 0x06){

        for(y = 0; y < (sizeof(command)/sizeof(command[0])); y++){
            while(Busy1USART());
            Write1USART(command[y]);
        }

        y = 0;
        while(y < (sizeof(response)/sizeof(response[0]))){
            if (DataRdy1USART()){
                response[y] = Read1USART();
                RCREG1 = 0x00;
                y++;
            }
            if ((y == 6) && (response[2] == 0x02)){
                // invalid
                break;
            }
        }

    } // end of while
}


void authenticate(void){
    // authenticates the tag for reading/writing

    unsigned char response[6] = { {0x00} };
    unsigned char command[7] = {0xFF, 0x00, 0x03, 0x85, 0x01, 0xFF, 0x88};


    while (response[4] != 0x4C){

        for(y = 0; y < (sizeof(command)/sizeof(command[0])); y++){
            while(Busy1USART());
            Write1USART(command[y]);
        }

        y = 0;
        while(y < (sizeof(response)/sizeof(response[0]))){
            if (DataRdy1USART()){
                response[y] = Read1USART();
                RCREG1 = 0x00;
                y++;
            }

        }

        if (response[4] != 0x4C){
            // authenticate failed
            selectTag();
        }

    } // end of while
}


int readBlock(void){
    // read the first block on the 1K tag

    unsigned char response[22] = { {0x00} };
    unsigned char command[6] = {0xFF, 0x00, 0x02, 0x86, 0x01, 0x89};
    int matchingBytes = 0;

    response[2] = 0x00;
    response[21] = 0x00;
    while(response[2] != 0x12){

        for(y = 0; y < (sizeof(command)/sizeof(command[0])); y++){
            while(Busy1USART());
            Write1USART(command[y]);
        }

        y = 0;
        while(y < (sizeof(response)/sizeof(response[0]))){
            if (DataRdy1USART()){
                response[y] = Read1USART();
                RCREG1 = 0x00;
                y++;
            }

            if(response[2] == 0x02 && y == 6){
                // read failed
                selectTag();
                authenticate();
                continue;
            }

        }

    } // end of while

    // read successful

    //check block one
    y = 0;
    matchingBytes = 0;
    for(z = 5; z < 21; z++){
        if(response[z] == blockOne[y]){
            matchingBytes++;
            y++;
        }
    }
    if (matchingBytes == 16) return 0; // block one was read (DEFAULT)

    //check block two
    y = 0;
    matchingBytes = 0;
    for(z = 5; z < 21; z++){
        if(response[z] == blockTwo[y]) {
            matchingBytes++;
            y++;
        }
    }
    if (matchingBytes == 16) return 1; // block two was read (POTION 1)

    //check block three
    y = 0;
    matchingBytes = 0;
    for(z = 5; z < 21; z++){
        if(response[z] == blockThree[y]) {
            matchingBytes++;
            y++;
        }
    }
    if (matchingBytes == 16) return 2; // block three was read (POTION 2)

    //check block four
    y = 0;
    matchingBytes = 0;
    for(z = 5; z < 21; z++){
        if(response[z] == blockFour[y]) {
            matchingBytes++;
            y++;
        }
    }
    if (matchingBytes == 16) return 3; // block four was read (POTION 3)


}


void writeBlock(int potNumb){
    // write data to the first block on the 1k tag

    unsigned char response[22] = { {0x00} };
    unsigned char data = 0x00; // DEFAULT
    unsigned char checksum = 0x9C;


    switch(potNumb){
        case 1: // Potion 1
            data = 0x40;
            break;
        case 2: // Potion 2
            data = 0x80;
            break;
        case 3: // Potion 3
            data = 0xC0;
            break;
        default: // DEFAULT
            data = 0x00;
            break;
    }

        response[2] = 0x00;
        while(response[2] != 0x12){

            //checksum = 0x12 + 0x89 + 0x01 + (0x16 * 0x40);

            while(Busy1USART());
            Write1USART(0xFF); // header
            while(Busy1USART());
            Write1USART(0x00); // reserved
            while(Busy1USART());
            Write1USART(0x12); // length
            while(Busy1USART());
            Write1USART(0x89); // command
            while(Busy1USART());
            Write1USART(0x01); // block

            // write data
            for(y = 0; y < 16; y++){
                while(Busy1USART());
                Write1USART(data);
            }

            while(Busy1USART());
            Write1USART(checksum); // checksum



            y = 0;
            while(y < (sizeof(response)/sizeof(response[0]))){
                if (DataRdy1USART()){
                    response[y] = Read1USART();
                    //RCREG1 = 0x00;
                    y++;
                }
            }
        }
}


int readIngred(void){
    int readTags = 0;
    int goodTags[3];

    while(readTags < 3){
        unsigned char tagRead[16] = { {0x00} };
        unsigned char formatTag[12] = { {0x00} };
        int theKeeper = 0;
        int matchingBytes = 0;

        // Read in tag
        
        x = 0;
        while(x < 16){
            if (DataRdy2USART()){
                tagRead[x] = Read2USART();
                RCREG1 = 0x00;
                x++;
            }
        }

        for (x = 0; x <= 16; x++){
            // Accept 0-9 and A-F as good tag reads
            if ( (tagRead[x] >= 0x30 && tagRead[x] <= 0x39)
                    || (tagRead[x] >= 0x41 && tagRead[x] <= 0x46) ){
                formatTag[theKeeper] = tagRead[x];
                theKeeper++;
            }
        }


        // check tag one
        matchingBytes = 0;
        for(z = 0; z < 12; z++){
            if (formatTag[z] == tagOne[z]){
                matchingBytes++;
            }
        }
        if (matchingBytes == 12){
            // make sure tag 1 hasn't been read already
            if(!(goodTags[0] == 1 || goodTags[1] == 1 || goodTags[2] == 1)){
                goodTags[readTags] = 1;
                playIngredientSong();
		setLED_ing(readTags, 1);
		readTags++;
            }
        }

        // check tag two
        matchingBytes = 0;
        for(z = 0; z < 12; z++){
            if (formatTag[z] == tagTwo[z]){
                matchingBytes++;
            }
        }
        if (matchingBytes == 12){
            // make sure tag 2 hasn't been read already
            if(!(goodTags[0] == 2 || goodTags[1] == 2 || goodTags[2] == 2)){
                goodTags[readTags] = 2;
                playIngredientSong();
		setLED_ing(readTags, 2);
		readTags++;
            }
        }

        // check tag three
        matchingBytes = 0;
        for(z = 0; z < 12; z++){
            if (formatTag[z] == tagThree[z]){
                matchingBytes++;
            }
        }
        if (matchingBytes == 12){
            // make sure tag 3 hasn't been read already
            if(!(goodTags[0] == 3 || goodTags[1] == 3 || goodTags[2] == 3)){
                goodTags[readTags] = 3;
                playIngredientSong();
		setLED_ing(readTags, 3);
		readTags++;
            }
        }

        // check tag four
        matchingBytes = 0;
        for(z = 0; z < 12; z++){
            if (formatTag[z] == tagFour[z]){
                matchingBytes++;
            }
        }
        if (matchingBytes == 12){
            // make sure tag 4 hasn't been read already
            if(!(goodTags[0] == 4 || goodTags[1] == 4 || goodTags[2] == 4)){
                goodTags[readTags] = 4;
                playIngredientSong();
		setLED_ing(readTags, 4);
		readTags++;
            }
        }

    } // End of reading while

	
    // Decide what potion was created
    // Change this to add or remove potion combinations
    if ((goodTags[0] == 1 && goodTags[1] == 2 && goodTags[2] == 3)
            || (goodTags[0] == 1 && goodTags[1] == 3 && goodTags[2] == 2)
            || (goodTags[0] == 2 && goodTags[1] ==3 && goodTags[2] == 1)
            || (goodTags[0] == 2 && goodTags[1] == 1 && goodTags[2] == 3)
            || (goodTags[0] == 3 && goodTags[1] == 2 && goodTags[2] == 1)
            || (goodTags[0] == 3 && goodTags[1] == 1 && goodTags[2] == 2)){
        // Potion 1 (HEAL)
        return 1;
    }
    else if((goodTags[0] == 1 && goodTags[1] == 3 && goodTags[2] == 4)
            || (goodTags[0] == 1 && goodTags[1] == 4 && goodTags[2] == 3)
            || (goodTags[0] == 3 && goodTags[1] == 4 && goodTags[2] == 1)
            || (goodTags[0] == 3 && goodTags[1] == 1 && goodTags[2] == 4)
            || (goodTags[0] == 4 && goodTags[1] == 3 && goodTags[2] == 1)
            || (goodTags[0] == 4 && goodTags[1] == 1 && goodTags[2] == 3)){
        // Potion 2 (ENVENOM)
        return 2;
    }
    else if((goodTags[0] == 1 && goodTags[1] == 2 && goodTags[2] == 4)
            || (goodTags[0] == 1 && goodTags[1] == 4 && goodTags[2] == 2)
            || (goodTags[0] == 2 && goodTags[1] == 4 && goodTags[2] == 1)
            || (goodTags[0] == 2 && goodTags[1] == 1 && goodTags[2] == 4)
            || (goodTags[0] == 4 && goodTags[1] == 2 && goodTags[2] == 1)
            || (goodTags[0] == 4 && goodTags[1] == 1 && goodTags[2] == 2)){
        // Potion 3 (POWER-UP)
        return 3;
    }
    else if((goodTags[0] == 2 && goodTags[1] == 3 && goodTags[2] == 4)
            || (goodTags[0] == 2 && goodTags[1] == 4 && goodTags[2] == 3)
            || (goodTags[0] == 3 && goodTags[1] == 4 && goodTags[2] == 2)
            || (goodTags[0] == 3 && goodTags[1] == 2 && goodTags[2] == 4)
            || (goodTags[0] == 4 && goodTags[1] == 2 && goodTags[2] == 3)
            || (goodTags[0] == 4 && goodTags[1] == 3 && goodTags[2] == 2)){
        // Potion 4 (EXPLOSION)
        return 4;
    }
    else{
        // Invalid potion (DEFAULT)
        return 0;
    }
}


void writePotion(int potNum){
    antennaOn();
    delay(100);
    selectTag();
//    all_off();
    authenticate();
//    all_off();
    writeBlock(potNum);
    // Delay turning off the antenna
    delay(500);
    antennaOff();
}


int readPotion(void){
	int potID;
	
	antennaOn();
        delay(100);
        selectTag();
        authenticate();
        potID = readBlock();
        // Delay resetting tag value
	delay(500);
        // Reset the value on the tag to DEFAULT
	writeBlock(0);
        // Delay turning off the antenna
	delay(500);		
	antennaOff();
        
	return potID;
}


void antennaOn(void){

    unsigned char command[6] = {0xFF, 0x00, 0x02, 0x90, 0x01, 0x93};
    unsigned char response[6] = { {0x00} };

    response[4] = 0x00;

    while(response[4] == 0x00){
        // !0x00 is antenna on

        for(y = 0; y < (sizeof(command)/sizeof(command[0])); y++){
            while(Busy1USART());
            Write1USART(command[y]);
        }

        y = 0;
        while(y < (sizeof(response)/sizeof(response[0]))){
            if (DataRdy1USART()){
                response[y] = Read1USART();
                RCREG1 = 0x00;
                y++;
            }

        }

    } // end of while

}


void antennaOff(void){
    unsigned char command[6] = {0xFF, 0x00, 0x02, 0x90, 0x00, 0x92};
    unsigned char response[6] = { {0xFF} };

    response[4] = 0xFF;

    while(response[4] != 0x00){
        // 0x00 is antenna off

        for(y = 0; y < (sizeof(command)/sizeof(command[0])); y++){
            while(Busy1USART());
            Write1USART(command[y]);
        }

        y = 0;
        while(y < (sizeof(response)/sizeof(response[0]))){
            if (DataRdy1USART()){
                response[y] = Read1USART();
                RCREG1 = 0x00;
                y++;
            }

        }

    } // end of while
}